/**
 * Created by Richard Radlherr.
 * Date: 28.05.2006 11:37
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using TagTool.Components;
using TagTool.Core;
using TagTool.Devices;
using TagTool.Nodes.Math;
using TagTool.OpenGL;
using TagTool.Nodes.Drawing;
using TagTool.Nodes.Graphic;
using TagTool.Nodes.Misc;
using TagTool.Nodes.Devices;
using System.Resources;
using System.Threading;


namespace TagTool
{
	public partial class MainForm : INodeUIController
	{
		NodePanel selected = null;
		Panel drawArea;
		
		String[] args;

		ProjectManager projectManager;
		
		MetaDataDialog metaDataDialog;
		
		[STAThread]
		public static void Main(string[] args)
		{
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			Application.Run(new MainForm(args));
		}
		
		MenuItem deleteNode = new MenuItem("Delete Node");
		
		public MainForm(String[] args)
		{
			
			
			this.args = args;
			projectManager = ProjectManager.GetInstance(this);
			
			metaDataDialog = new MetaDataDialog(this);
			
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();

			//drawArea = this.mainArea.Panel2;
			drawArea = this.panelDraw;
			drawArea.AutoScrollOffset = new Point(5000, 5000);

            AssemblyManager.GetInstance("TagTool.Nodes.Math.dll");
            AssemblyManager.GetInstance("TagTool.Nodes.Misc.dll");
            AssemblyManager.GetInstance("TagTool.Nodes.Drawing.dll");
            AssemblyManager.GetInstance("TagTool.Nodes.Graphic.dll");
            AssemblyManager.GetInstance("TagTool.Nodes.Devices.dll");

			browsePanel.InitializeTreeView();
			this.SetBounds(0, 300, 1280, 768 - 330);
			
			Icon = new Icon(@"tagTool.ico");
			menuOptionsProgramModeUI.CheckState = CheckState.Checked;
		}
		
		protected override void OnShown(EventArgs e) {
			ParseArgs();
		}
		
		public void ParseArgs() {
			String file = null;
			int stage = -1;
			try {
				foreach (String arg in args) {
					if (arg.StartsWith("-file:")) {
						file = arg.Substring(6);
					} else if (arg.StartsWith("-stage:")) {
						stage = int.Parse(arg.Substring(7));
					}
				}
				if (null != file) {
					Open(file);
					if (stage > -1) {
						menuOptionsProgramModeUI.CheckState = CheckState.Unchecked;
						AttachUI();
						projectManager.GetStage(stage).Content.FullScreen = true;
					}
				}
			} catch (Exception ex) {
				Console.WriteLine("Invalid arguments!" + ex.Message);
			}
		}
		
		void SelectNode(Object sender, System.EventArgs e)
		{
			selected = (NodePanel)sender;
			selected.BringToFront();
		}
		
		public String MetaData
		{
			get { return metaDataDialog.Metadata; }
			set { metaDataDialog.Metadata = value; }
		}
		
		public String SessionName
		{
			get { return metaDataDialog.SessionName; }
		}


		public void RemoveNode(BaseNode node)
		{
			// TODO: implement.	
		}
	
		public void AddNode(BaseNode node, int x, int y)
		{
			NodePanel panel = new NodePanel();
			panel.Node = node;
			
			panel.Left = x - panel.Width / 2 + mainArea.Panel2.HorizontalScroll.Value;
            panel.Top = y - 12 + mainArea.Panel2.VerticalScroll.Value;
			node.LocX = panel.Left;
			node.LocY = panel.Top;

			panel.Enter += new EventHandler(SelectNode);

			drawArea.Controls.Add(panel);
			panel.Select();
		}
        
		public void AddNode(BaseNode node)
		{
			NodePanel panel = new NodePanel();
			
			panel.Node = node;

			panel.Enter += new EventHandler(SelectNode);

			drawArea.Controls.Add(panel);
			panel.Select();
		}
		
		public void ConnectSlots(InputSlot s1, OutputSlot s2)
		{
			InputSlotPanel input = null;
			OutputSlotPanel output = null;
			foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					if (input == null) input = ((NodePanel)c).Find(s1);
					if (output == null) output = ((NodePanel)c).Find(s2);
				}
			}
			
			if (input != null && output!= null)
			{
				input.Connect(output);
			}
			
			drawArea.Invalidate();
		}

		
		void BrowsePanelNodeDoubleClick(object sender, TagTool.Components.NodeDoubleClickedEventArgs e)
		{
			try 
			{
				AddNode(e.Node, 100, 100);
			}
			catch {}
		}
		
		void MenuOptionsAddNodeCollectionClick(object sender, System.EventArgs e)
		{
			browsePanel.LoadAssembly();
		}
		
		void DrawAreaDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
		{
			IDataObject o = e.Data;
			if (o.GetDataPresent(typeof(System.Windows.Forms.TreeNode)) || o.GetDataPresent(typeof(InputSlotPanel)) )
			{
				e.Effect = DragDropEffects.Move;
			}
		}

		void DrawAreaDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			IDataObject o = e.Data;
			if (o.GetDataPresent(typeof(System.Windows.Forms.TreeNode)))
			{
				TreeNode tn = (TreeNode)o.GetData(typeof(System.Windows.Forms.TreeNode));
				if (tn.Parent != null)
				{
					AddNode(projectManager.CreateNode(tn.Parent.Text, tn.Text), e.X - mainArea.SplitterDistance - Left - 8 , e.Y - mainArea.Top - Top - 23);
				}
			}
			else if (o.GetDataPresent(typeof(InputSlotPanel)))
			{
				InputSlotPanel slot = (InputSlotPanel)o.GetData(typeof(InputSlotPanel));
				slot.UnConnect();
				drawArea.Invalidate();
			}
		}
		
		
		void AddAssemblyClick(object sender, System.EventArgs e)
		{
			browsePanel.LoadAssembly();
		}

		void DrawAreaPaint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					((NodePanel)c).PaintConnections(e.Graphics);
				}
			}
		}

		void RemoveNodePanel(NodePanel nodePanel)
		{
			if (nodePanel != null)
			{
				nodePanel.Dispose();
				drawArea.Invalidate();
			}
		}
		
		void MenuEditDeleteClick(object sender, System.EventArgs e)
		{
			RemoveNodePanel(selected);
		}
		
		public IStage CreateStage(String name)
		{
			return new StageForm(projectManager, name);
		}

		void AttachRenderableNodeToStageToolStripMenuItemClick(object sender, System.EventArgs e)
		{
			if ((selected != null) && (selected.Node is RenderableNode) && projectManager.StageCount > 0)
			{
				projectManager.GetStage(0).Content = (RenderableNode)selected.Node;
			}
		}

		void MainFormKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete)
			{
				RemoveNodePanel(selected);
			}
		}

		public void SaveAs()
		{
			if (DialogResult.OK == saveFileDialog.ShowDialog())
            {
			 	Save();
            }
		}
		
		public void Save()
		{
			try
            {
                projectManager.Save(saveFileDialog.FileName);
            }
			catch (Exception)
            {
                MessageBox.Show("Die Datei " + saveFileDialog.FileName + " konnte nicht gespeichert werden.", "Fehler beim Speichern");
            }
		}
		
        void MenuFileSaveClick(object sender, System.EventArgs e)
        {
        	Save();
        }
        
        public void Open(String fileName) {
        	New();
            try
            {
                projectManager.Load(fileName, this);
                saveFileDialog.FileName = fileName;
                openFileDialog.FileName = fileName;
            }
            catch (Exception)
            {
                MessageBox.Show("Die Datei " + fileName + " konnte nicht geladen werden.", "Fehler beim Laden");
                this.New();
            }
            finally
            {
                browsePanel.InitializeTreeView();
            }

			GC.Collect();
        }
		
		void MenuFileOpenClick(object sender, System.EventArgs e)
		{
			//projectManager.Load("Test.tagproj", this);
            if (DialogResult.OK == openFileDialog.ShowDialog())
            {
            	Open(openFileDialog.FileName);
            }
		}
		
		private void New()
		{
			foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					c.Dispose();
				}
			}
			drawArea.Controls.Clear();
			projectManager.New();
			drawArea.Invalidate();
		}
		
		void MenuFileNewClick(object sender, System.EventArgs e)
		{
			New();
		}

        private void CollapseClick(object sender, EventArgs e)
        {
            foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					((NodePanel)c).Collapse();
				}
			}
        }

        private void ExpandClick(object sender, EventArgs e)
        {
            foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					((NodePanel)c).Expand();
				}
			}
        }
		
        public bool ShowUpdate
		{
        	get { return menuOptionsProgramModeUI.CheckState == CheckState.Checked; }
		}
        
		void MenuFileSaveAsClick(object sender, System.EventArgs e)
		{
			SaveAs();
		}
		
		void MenuFileExitClick(object sender, System.EventArgs e)
		{
			Close();
		}
		
		private void AttachUI()
		{
			foreach(Control c in drawArea.Controls)
			{
				if (c is NodePanel)
				{
					
					switch (menuOptionsProgramModeUI.CheckState)
					{
						case CheckState.Checked:	
							((NodePanel)c).Attach();
						break;
						
						case CheckState.Unchecked:
							((NodePanel)c).Detach();
						break;
					}
					
				}
			}
		}
		
		void MenuOptionsProgramModeUIClick(object sender, System.EventArgs e)
		{
			AttachUI();
		}
		
		
		
		void EditMetadataToolStripMenuItemClick(object sender, System.EventArgs e)
		{
			metaDataDialog.Show(this);
		}
	}
	
}
